function Action(type)
{
	/**
	 * Action attributes
	 */
	this.type = type;
}

Action.prototype.build = function (data)
{
	var query = this.type;
	
	jQuery.each(
		Action.types[this.type].fields, function ()
		{
			query += '/' + data[this.name];
		});
	
	this.query = query;
}

Action.prototype.execute = function (data)
{
	if (this.query === undefined) {
		this.build(data);
	}
	
	// TODO : Test macro mode for this action ; add it to the macro log if true
	(new Request(
		this.query,
		Action.types[this.type].complete
	)).execute();
}

var i = 0;
Action.Atoms = {
	STREAM:    ++i,
	VALUE:     ++i,
	SQL:       ++i,
	BINARY:    ++i,
	TERNARY:   ++i,
	ITERATOR:  ++i,
	TIMESTAMP: ++i
};

Action.COMPOSITE = ++i;
Action.SIMPLE    = ++i;

Action.types = {
	'new': {
		type:   Action.COMPOSITE,
		fields: {
			'stream':      [
				{name: 'name',            type: Action.Atoms.STREAM}],
			'import':      [
				{name: 'query',           type: Action.Atoms.SQL},
				{name: 'name',            type: Action.Atoms.STREAM}],
			'operator':    [
				{name: 'left',            type: Action.Atoms.STREAM},
				{name: 'right',           type: Action.Atoms.STREAM},
				{name: 'operation',       type: Action.Atoms.BINARY},
				{name: 'name',            type: Action.Atoms.STREAM}],
			'filter':      [
				{name: 'source',          type: Action.Atoms.STREAM},
				{name: 'startTimeFilter', type: Action.Atoms.TERNARY},
				{name: 'endTimeFilter',   type: Action.Atoms.TERNARY},
				{name: 'valueFilter',     type: Action.Atoms.TERNARY},
				{name: 'filterCondition', type: Action.Atoms.TERNARY},
				{name: 'name',            type: Action.Atoms.STREAM}],
			'union':       [
				{name: 'left',            type: Action.Atoms.STREAM},
				{name: 'right',           type: Action.Atoms.STREAM},
				{name: 'name',            type: Action.Atoms.STREAM}],
			// TODO: Integrate support for aggregations
			// 'aggregation': [
			// 	{name: 'source', type: Action.Atoms.STREAM},
			// 	'aggregationStartTimeIterator',
			// 	'aggregationEndTimeIterator',
			// 	'aggregationValueIterator',
			// 	'aggregationGrouper',
			// 	{name: 'name', type: Action.Atoms.STREAM}],
			'iterator':    [
				{name: 'source',          type: Action.Atoms.STREAM},
				{name: 'iterator',        type: Action.Atoms.ITERATOR},
				{name: 'name',            type: Action.Atoms.STREAM}],
			'duplicate':   [
				{name: 'source',          type: Action.Atoms.STREAM},
				{name: 'name',            type: Action.Atoms.STREAM}],
			'normalize':   [
				{name: 'source',          type: Action.Atoms.STREAM},
				{name: 'name',            type: Action.Atoms.STREAM}]},
		macro:  true,
		complete: function (data)
		{
			Stream.push(data);
		}},
	'list':   {
		type:    Action.SIMPLE,
		fields:  [],
		macro:   false,
		complete: function (data)
		{
			jQuery.each(
				data, function ()
				{
					Stream.push(this);
				});
		}},
	'get':    {
		type:    Action.SIMPLE,
		fields:  [
			{name: 'name',                type: Action.Atoms.STREAM}],
		macro:   false,
		complete: function (data, action)
		{
			// FIXME: How do we know for which stream we are providing data ?
			Stream.streams[action.name]
				.setDataFromRaw(data);
		}},
	'set':    {
		type:   Action.SIMPLE,
		fields: [
			{name: 'name',                type: Action.Atoms.STREAM},
			{name: 'startTime',           type: Action.Atoms.TIMESTAMP},
			{name: 'endTime',             type: Action.Atoms.TIMESTAMP},
			{name: 'value',               type: Action.Atoms.VALUE}],
		macro:  true,
		complete: function (data)
		{
			(new Action('get')).execute(data);
		}},
	'delete': {
		type:     Action.SIMPLE,
		fields:   [
			{name: 'name',                type: Action.Atoms.STREAM}],
		macro:    true,
		complete: function (data)
		{
			Stream.remove(data);
		}},
	'quit':   {
		type:     Action.SIMPLE,
		fields:   [],
		macro:    false,
		complete: function (data)
		{
			log.push('Quitting...');
		}}};

/**
 * Handling action log
 */
Action.push = function (info)
{
	Action.log.push(new Action(info));
}

Action.clear = function ()
{
	Action.log = []
}

Action.clear();
